<script>
/**
 * 全局公共配置
 */
/**
 * 搜索模块 组件
 * 必须接受的 props
 *
 * colums (表格的配置项) - 必传
 * filter (要绑定的对象)
 * setting (设置 - 更多搜索等)
 */
import { getColumMinWidth } from "./utils/columSetting.js";
import moment from "moment";

import { h, ref, reactive } from "vue";

import { Column } from "vxe-table";
// import * as filters from "@/util/allfilter";

const setting = {
  showOverflow: true, // 单元格内容是否超出省略号
  sortable: true,
  formSize: "mini", // 表单组件大小
  Formclearable: true, // 表单组件是否可清空
};

export default {
  name: "TableColum",
  setup(props, context) {
    // console.log("context ==>", context);
    /**
     * Render 页面生成
     */
    const items = itemsRender();
    return () => h("div", {}, items);
    /**
     * 渲染 搜索组件
     */
    function itemsRender() {
      const colums = context.attrs.colums;
      // console.log("colums ==>", colums);
      const res = [];
      for (const i in colums) {
        res.push(columRender(colums[i], i));
      }
      return res;
    }
    /**
     * 渲染根元素 vxe-column
     */
    function columRender(attrs, i) {
      // 判断是否传入showOverflow、sortable，否则使用默认的值
      const showOverflow =
        attrs.props && typeof attrs.props.showOverflow === "boolean"
          ? attrs.showOverflow
          : setting.showOverflow;
      const sortable =
        attrs.props && typeof attrs.props.sortable === "boolean"
          ? attrs.sortable
          : setting.sortable;
      // debugger;
      attrs.props = columProps(attrs); // 重构props的宽度展示

      const props = {
        ...attrs.props,
        field: i,
        title: attrs.title,
        showOverflow,
        sortable,
      };

      // console.log("props ==>", props);

      if (
        !attrs.more &&
        !attrs.slotHeader &&
        !attrs.slotContent &&
        !attrs.contentKey
      ) {
        return h(Column, {
          ...props,
        });
      }
      return h(
        Column,
        {
          ...props,
        },
        {
          // 插槽引入
          header: (props) => {
            // 自定义头部
            const slotHeader = attrs.slotHeader;
            if (slotHeader) return slotRender(slotHeader, i, props); // 渲染插槽节点
            return columHeaderRender(attrs, i);
          },
          default: (props) => {
            // 自定义内容
            const slotContent = attrs.slotContent;
            if (slotContent) return slotRender(slotContent, i, props); // 渲染插槽节点
            return columContentRender(attrs, i, props);
          },
        }
      );
    }
    /**
     * vxe-column 的自定义头部渲染
     */
    function columHeaderRender(attrs, i) {
      if (
        attrs.more &&
        context.props.setting &&
        context.props.setting.moreSearch
      ) {
        // 是否渲染表单
        const type = attrs.more.type || "input";
        const typeMap = {
          input: inputRender,
          select: selectRender,
          "date-picker": datePickerRender,
          "date-picker-two": datePickerTwoRender,
          "input-two": inputTwoRender,
        };
        const filterAttrs = {
          ...attrs.more,
          label: attrs.title,
        };
        const component = typeMap[type](filterAttrs, attrs.more.key || i);
        return component;
      }
      const spanHeader = attrs.title;
      // if (attrs.headerFilters && Array.isArray(attrs.headerFilters)) {
      //   // 过滤器
      //   for (const v of attrs.headerFilters) {
      //     spanHeader = filters[v](spanHeader);
      //   }
      // }
      return h("span", spanHeader);
    }
    /**
     * vxe-column 的自定义内容渲染
     */
    function columContentRender(attrs, i, props) {
      const spanContent = props.row[attrs.contentKey || i];
      // if (attrs.contentFilters && Array.isArray(attrs.contentFilters)) {
      //   // 过滤器
      //   for (const v of attrs.contentFilters) {
      //     spanContent = filters[v](spanContent);
      //   }
      // }
      return h("span", null, spanContent);
    }
    /**
     * 获取slot插槽节点
     */
    function slotRender(name, i, props) {
      // console.log("slotRender   ====> name", name);
      // console.log("slotRender   ====> props", props);
      const slots = context.slots;
      if (slots && slots[name]) {
        const vnode = slots[name]({ props });
        return vnode;
      }
      return null;
    }
    /**
     * 表单组件的渲染方法
     */
    // el-input
    function inputRender(attrs, i, className = "") {
      const props = attrs.props || {};
      if (!props.placeholder) props.placeholder = attrs.label;
      return h("el-input", {
        class: className,
        ...elModel(i, { ...attrs, props }, "input"),
      });
    }
    // el-input区间
    function inputTwoRender(attrs, i) {
      const attrsMin = getInputTwoProps(attrs, "min");
      const attrsMax = getInputTwoProps(attrs, "max");
      return h(
        "div",
        {
          class: "th-box",
        },
        [
          inputRender(attrsMin, `${i}Min`, "th-input"),
          inputRender(attrsMax, `${i}Max`, "th-input"),
        ]
      );
    }
    // el-select
    function selectRender(attrs, i) {
      const props = attrs.props || {};
      props.placeholder = attrs.label;
      const options = computedOptions(attrs);
      return h(
        "el-select",
        {
          style: {
            // width: getInputWidth(attrs.label)
          },
          ...elModel(i, { ...attrs, props }, "change"),
        },
        options.map(optionRender)
      );
    }
    // el-option
    function optionRender(attrs = {}) {
      return h(
        "el-option",
        {
          props: {
            label: attrs.label,
            value: attrs.value,
            disabled: attrs.disabled || false,
          },
        },
        attrs.render ? attrs.render(h) : []
      );
    }
    // el-date-picker
    function datePickerRender(attrs, i, className = "") {
      return h("el-date-picker", {
        class: className,
        ...elModel(i, attrs, "input"),
      });
    }
    // el-date-picker区间
    function datePickerTwoRender(attrs, i) {
      const attrsStart = getDatePickerTwoProps(attrs, "start");
      const attrsEnd = getDatePickerTwoProps(attrs, "end");
      return h(
        "div",
        {
          class: "th-box",
        },
        [
          datePickerRender(attrsStart, `${i}Start`, "th-input"),
          datePickerRender(attrsEnd, `${i}End`, "th-input"),
        ]
      );
    }
    /**
     * element组件的双向绑定
     */
    function elModel(key, attrs = {}, type = "input") {
      // 处理自定义指令
      const directives = [];
      if (attrs.directives) {
        for (const key in attrs.directives) {
          directives.push({
            name: key,
            value: attrs.directives[key],
          });
        }
      }
      return {
        ...attrs,
        attrs: {
          ...attrs.props,
          ...attrs.attrs,
        },
        props: {
          size: setting.formSize,
          clearable: setting.Formclearable,
          ...attrs.props,
          value: context.props.filter[key],
        },
        // el-selct 触发原生的change事件
        // el-date-picker 触发原生的input事件
        on: {
          ...attrs.on,
          [type](e) {
            if (attrs.type === "date-picker") {
              // 日期组件的特殊处理
              if (e === null) {
                // 用于清空
                context.props.filter[key] = null;
                return;
              }
              let dateType = "YYYY-MM-DD";
              if (
                attrs.props &&
                attrs.props.valueFormat === "yyyy-MM-dd HH:mm:ss"
              )
                dateType = "YYYY-MM-DD HH:mm:ss";
              if (moment(e).format(dateType) === e)
                context.props.filter[key] = e;
            } else context.props.filter[key] = e;
          },
        },
        // el-input 触发组件的input事件
        nativeOn: {
          ...attrs.nativeOn,
          [type](e) {
            if (attrs.type === "date-picker") {
              // 日期组件的特殊处理
              if (e === null) {
                // 用于清空
                context.props.filter[key] = null;
                return;
              }
              let dateType = "YYYY-MM-DD";
              if (
                attrs.props &&
                attrs.props.valueFormat === "yyyy-MM-dd HH:mm:ss"
              )
                dateType = "YYYY-MM-DD HH:mm:ss";
              if (moment(e.target.value).format(dateType) === e.target.value)
                context.props.filter[key] = e.target.value;
            } else context.props.filter[key] = e.target.value;
          },
        },
        directives: directives,
      };
    }
    /**
     * 获取计算后的options
     */
    function computedOptions(attrs) {
      const options = attrs.options;
      const {
        value = "val",
        label = "label",
        type = String,
      } = attrs.optionKey || {};
      let results = [];
      if (Array.isArray(options)) {
        results = options.map((item) => {
          return {
            value: type(item[value]),
            label: item[label],
          };
        });
      } else {
        for (const key in options) {
          results.push({
            value: type(key),
            label: options[key],
          });
        }
      }
      return results;
    }
    /**
     * 处理表格的宽度展示
     */
    function columProps(attrs) {
      const props = attrs.props || {};
      // console.log("columProps ===> props", props);
      if (props.width === undefined && props.minWidth === undefined) {
        // const columSetting = context.attrs.setting || {};
        let minWidth = "";
        // if (columSetting.moreSearch && attrs.more && attrs.more.width)
        //   minWidth = attrs.more.width;
        // // 更多搜索且自定义宽度
        // else if (!props.width) minWidth = columMinWidth(attrs); // 自动计算宽度
        minWidth = columMinWidth(attrs); // 自动计算宽度
        // console.log("columProps ===> minWidth", minWidth);
        if (minWidth !== "") {
          // 需要根据minWidth展示
          if (props.width) delete props.width; // 删除width，否则minWidth会失效
          props.minWidth = minWidth;
        }
      }

      return props;
    }
    /**
     * 更多搜索根据控件类型自动计算宽度
     * 默认内容展示根据文字长度计算宽度
     */
    function columMinWidth(attrs) {
      const columSetting = context.attrs.setting;
      let type = (attrs.more && attrs.more.type) || "default";
      if (attrs.more) {
        if (attrs.more.type) type = attrs.more.type;
        if (type === "date-picker-two" && attrs.more.props) {
          type =
            attrs.more.props.valueFormat === "yyyy-MM-dd HH:mm:ss"
              ? "date-picker-two-time"
              : "date-picker-two";
        }
        if (type === "date-picker" && attrs.more.props) {
          type =
            attrs.more.props.valueFormat === "yyyy-MM-dd HH:mm:ss"
              ? "date-picker-time"
              : "date-picker";
        }
      }
      // console.log(11111, attrs);
      return getColumMinWidth(
        attrs.title,
        type,
        columSetting && columSetting.moreSearch
      );
    }
    /** 处理日期区间的相关参数 */
    function getDatePickerTwoProps(attrs, type) {
      let defaultTime = type === "start" ? "00:00:00" : "23:59:59";
      const placeholder = attrs.label + (type === "start" ? "开始" : "结束");
      let pickerOptions = {};
      if (attrs.props) {
        // placeholder
        if (attrs.props.pickerOptionsStart && type === "start") {
          // 开始日期限制选择
          pickerOptions = attrs.props.pickerOptionsStart;
        }
        if (attrs.props.pickerOptionsStart && type === "end") {
          // 结束日期限制选择
          pickerOptions = attrs.props.pickerOptionsEnd;
        }
        // defaultTime
        if (attrs.props.defaultTimeStart && type === "start")
          defaultTime = attrs.props.defaultTimeStart;
        if (attrs.props.defaultTimeEnd && type === "end")
          defaultTime = attrs.props.defaultTimeEnd;
      }

      const data = {
        label: attrs.label,
        props: {
          ...attrs.props,
          defaultTime,
          placeholder,
          pickerOptions,
        },
        directives: attrs.directives,
        type: "date-picker",
      };
      return data;
    }
    /** 处理输入区间的相关参数 */
    function getInputTwoProps(attrs, type) {
      const placeholder = attrs.label + (type === "min" ? "最小值" : "最大值");
      const data = {
        label: attrs.label,
        props: {
          ...attrs.props,
          placeholder,
        },
        directives: attrs.directives,
        type: "el-input",
      };
      return data;
    }
  },
};
</script>

<style scoped></style>
